# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

# Build definitions for OTBN software
#
# OTBN software is built with a separate toolchain, which is called as an
# external target from Meson. All functionality to call the external toolchain
# is encapsulated in this build file; users only need to care about two
# dictionaries.
#
# To use an OTBN application in device software, use the sw_lib_crypto_otbn
# dictionary.  For example, to add a dependency to an embeddable version of the
# barrett384 OTBN application, add the following variable to the list of
# dependencies: sw_lib_crypto_otbn['barrett384']['rv32embed_dependency']
#
# The sw_lib_crypto_otbn dictionary has the following structure:
# sw_lib_crypto_otbn = {
#   APPNAME: {
#     'elf': OTBN_ELF_FILE,
#     'rv32embed_lib': RV32_LIBRARY,
#     'rv32embed_dependency': DEPENDENCY_ON_RV32_LIBRARY,
# }}
#
# Note that application names must be unique across subdirectories.

# All OTBN software is added to this dictionary and then built in one go.
sw_lib_crypto_otbn_sources = {}

# All subdirectories add the objects they want to build to the
# sw_lib_crypto_otbn_sources dictionary.
subdir('ecdsa_p256')

prog_otbn_build = meson.source_root() / 'util/otbn_build.py'

otbn_build_command = [
  prog_env,
  'OTBN_AS=@0@'.format(prog_otbn_as),
  'OTBN_LD=@0@'.format(prog_otbn_ld),
  'RV32_TOOL_OBJCOPY=@0@'.format(prog_objcopy.path()),
  'RV32_TOOL_AS=@0@'.format(prog_as.path()),
  'RV32_TOOL_LD=@0@'.format(prog_ld.path()),
  prog_python,
  prog_otbn_build,
  '--out-dir',
  '@OUTDIR@',
  '@INPUT@',
]
otbn_build_depend_files = [
  prog_otbn_as,
  prog_otbn_ld,
  prog_objcopy.path(),
  prog_as.path(),
  prog_ld.path(),
  prog_otbn_build,
]

# Note on variable naming below: Variables in meson are global, we hence prefix
# all variables with sw_lib_crypto_otbn as "our namespace". Variables which are meant to be
# local to this file are prefixed with `sw_lib_crypto_otbn__`.

sw_lib_crypto_otbn = {}
foreach sw_lib_crypto_otbn__app_name, sw_lib_crypto_otbn__app_sources : sw_lib_crypto_otbn_sources
  # Output files generated by the otbn_build.py script.
  sw_lib_crypto_otbn__app_output_files = [
    sw_lib_crypto_otbn__app_name + '.rv32embed.o',
    sw_lib_crypto_otbn__app_name + '.elf',
  ]

  # Target calling otbn_build.py
  sw_lib_crypto_otbn__target = custom_target(
    'sw_lib_crypto_otbn_apps_' + sw_lib_crypto_otbn__app_name + '_target',
    input: sw_lib_crypto_otbn__app_sources,
    output: sw_lib_crypto_otbn__app_output_files,
    command: otbn_build_command,
    depend_files: [otbn_build_depend_files,],
  )

  # A library containing the OTBN application in a form embeddable into device
  # (Ibex) software (the *.rv32embed.o file).
  sw_lib_crypto_otbn__embedded_lib = static_library(
    sw_lib_crypto_otbn__app_name,
    [sw_lib_crypto_otbn__target[0]] # == sw_lib_crypto_otbn__app_output_files[0], i.e. *.rv32embed.o
  )

  # A dependency on the application as embeddable library, to be used if
  # device (Ibex) software wants to include an OTBN application in its binary.
  sw_lib_crypto_otbn__dependency = declare_dependency(
    link_with: sw_lib_crypto_otbn__embedded_lib,
  )

  sw_lib_crypto_otbn += {
    sw_lib_crypto_otbn__app_name: {
      'elf': sw_lib_crypto_otbn__target[1],
      'rv32embed_lib': sw_lib_crypto_otbn__embedded_lib,
      'rv32embed_dependency': sw_lib_crypto_otbn__dependency,
    }
  }

  custom_target(
    'sw_lib_crypto_otbn_app_export_' + sw_lib_crypto_otbn__app_name,
    command: export_target_command,
    depend_files: [export_target_depend_files,],
    input: [sw_lib_crypto_otbn__target[1]],
    output: 'sw_lib_crypto_otbn_app_export_' + sw_lib_crypto_otbn__app_name,
    build_always_stale: true,
    build_by_default: true,
  )

endforeach
